package org.edu.modules.jxrw.controller;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.edu.common.api.vo.Result;
import org.edu.common.aspect.annotation.AutoLog;
import org.edu.common.system.vo.LoginUser;
import org.edu.modules.classSchedule.entity.VeJwSection;
import org.edu.modules.classSchedule.service.IVeJwSectionService;
import org.edu.modules.jxrw.api.CommonApi;
import org.edu.modules.jxrw.api.IScheduleApi;
import org.edu.modules.jxrw.api.IVeJwJxzyFeignClientService;
import org.edu.modules.jxrw.entity.PkParam;
import org.edu.modules.jxrw.entity.PkmxResult;
import org.edu.modules.jxrw.service.IExcelService;
import org.edu.modules.jxrw.vo.Course;
import org.edu.modules.scheduleCommon.entity.VeBaseAppUser;
import org.edu.modules.scheduleCommon.entity.VeBaseSemester;
import org.edu.modules.scheduleCommon.entity.VeBaseStudent;
import org.edu.modules.scheduleCommon.service.VeBaseAppUserService;
import org.edu.modules.scheduleCommon.service.VeBaseSemesterService;
import org.edu.modules.scheduleCommon.service.VeBaseStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 课表查询
 * @Author: xlz
 * @Date: 2021-06-24
 */
@Api(tags = "课表查询")
@Slf4j
@RestController
@RequestMapping("/jxrw/kbcx")
public class VeJwKeBiaoChaXunController {

    @Autowired
    private CommonApi commonApi;
    @Autowired
    private IScheduleApi scheduleApi;
    @Autowired
    private IVeJwJxzyFeignClientService jxzyApi;
    @Autowired
    private IExcelService excelService;

    @Autowired
    private VeBaseAppUserService veBaseAppUserService;

    @Autowired
    private VeBaseStudentService veBaseStudentService;

    @Autowired
    private VeBaseSemesterService veBaseSemesterService;

    @Autowired
    private IVeJwSectionService veJwSectionService;

    /**
     * 我的课表查询
     *
     * @return 班级课表
     */
    @AutoLog(value = "我的课表查询")
    @ApiOperation(value = "我的课表查询", notes = "我的课表查询")
    @GetMapping("/wdkb")
    public Result<JSONObject> wdkb() {

        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //根据用户id查用户信息
        VeBaseAppUser appUser = veBaseAppUserService.getVeBaseAppUserById(loginUser.getId());
        //ArrayList<Course> courseList = new ArrayList<>();
        JSONObject result = new JSONObject();
        if (appUser.getUserType().contains("2")) {
            //如果是学生账号，查当前学生的班级
            //根据学号查班级
            VeBaseStudent baseStudent = veBaseStudentService.findByUserId(appUser.getUserId());
            //获取当前学期
            VeBaseSemester currentSemester = veBaseSemesterService.getCurrentSemester();
            // 获取排课信息；列表
            List<JSONObject> paikeList = scheduleApi.queryPaiKe(PkParam.getBySemidAndJxbid(currentSemester.getId(), baseStudent.getBjId())).getResult().getRecords();
            // 排课明细数据
            List<PkmxResult> data = this.getPkmxList(currentSemester.getId(), baseStudent.getBjId(), paikeList);
            this.sort(data);
            this.checkIsHb(data);
            if (paikeList.size() > 0) {
                result.put("semester", paikeList.get(0).getString("xqmc"));
                result.put("bjName", paikeList.get(0).getString("jxbmc"));
                result.put("xqmc", currentSemester.getXqmc());
            }
            result.put("data", data);
            /*for (PkmxResult pkmxResult:pkmxList){
               VeJwSection veJwSection = veJwSectionService.getById(pkmxResult.getSection());
               Course course = new Course();
               course.setId(pkmxResult.getId());
               course.setCourseId(pkmxResult.getKcid());
               course.setCourseName(pkmxResult.getKcmc());
               course.setClassroomId(pkmxResult.getJsid());
               course.setClassroomName(pkmxResult.getJsmc());
               course.setTeacherId(pkmxResult.getTeacherid());
               course.setAttendTime(veJwSection.getKssj());
               course.setFinishTime(veJwSection.getJssj());
               course.setTeacherName(pkmxResult.getJsxm());
               courseList.add(course);
           }
        }
        return Result.OK(courseList);*/
        }
        return Result.OK(result);
    }

    /**
     * 班级课表查询
     *
     * @param semid  学期id
     * @param xzbids 行政班id
     * @return 班级课表
     */
    @AutoLog(value = "课表查询-班级课表查询")
    @ApiOperation(value = "课表查询-班级课表查询", notes = "课表查询-班级课表查询")
    @GetMapping("/bjkb")
    public Result<JSONObject> banJiKeBiao(@RequestParam Integer semid, @RequestParam Integer xzbids) {

        // 获取排课信息；列表
        List<JSONObject> paikeList = scheduleApi.queryPaiKe(PkParam.getBySemidAndJxbid(semid, xzbids)).getResult().getRecords();
        // 排课明细数据
        List<PkmxResult> data = this.getPkmxList(semid, xzbids, paikeList);
        this.sort(data);
        this.checkIsHb(data);

        JSONObject result = new JSONObject();
        if (paikeList.size() > 0) {
            result.put("semester", paikeList.get(0).getString("xqmc"));
            result.put("bjName", paikeList.get(0).getString("jxbmc"));
        }

        result.put("data", data);
        return Result.OK(result);
    }

    /**
     * 教师课表查询
     *
     * @param semid     学期id
     * @param teacherid 教师账号id
     * @return 教师课表
     */
    @AutoLog(value = "课表查询-教师课表查询")
    @ApiOperation(value = "课表查询-教师课表查询", notes = "课表查询-教师课表查询")
    @GetMapping("/lskb")
    public Result<JSONObject> lskb(@RequestParam Integer semid, @RequestParam Integer teacherid) {
        JSONObject result = new JSONObject();
        List<PkmxResult> data = scheduleApi.queryLaoShiKeBiao(semid, teacherid).getResult().getRecords();
        this.sort(data);
        this.checkIsHb(data);

        JSONObject semester = commonApi.querySemesterById(CommonApi.COMMON_TOKEN_KEY, semid).getResult();
        result.put("semester", semester != null ? semester.getString("xqmc") : "");
        JSONObject laoshi = commonApi.queryTeacherByUserId(CommonApi.COMMON_TOKEN_KEY, teacherid.toString()).getResult();
        result.put("lsName", laoshi != null ? laoshi.getString("xm") : "");

        result.put("data", data);
        return Result.OK(result);
    }

    /**
     * 教室课表查询
     *
     * @param semid 学期id
     * @param jsid  教室id
     * @return 教室课表
     */
    @AutoLog(value = "课表查询-教室课表查询")
    @ApiOperation(value = "课表查询-教室课表查询", notes = "课表查询-教室课表查询")
    @GetMapping("/jskb")
    public Result<JSONObject> jskb(@RequestParam Integer semid, @RequestParam Integer jsid) {
        JSONObject result = new JSONObject();
        List<PkmxResult> data = scheduleApi.queryJiaoShiKeBiao(semid, jsid).getResult().getRecords();
        this.sort(data);
        this.checkIsHb(data);

        JSONObject semester = commonApi.querySemesterById(CommonApi.COMMON_TOKEN_KEY, semid).getResult();
        result.put("semester", semester != null ? semester.getString("xqmc") : "");
        result.put("jsName", jxzyApi.queryNameById(jsid));

        result.put("data", data);
        return Result.OK(result);
    }

    /**
     * 专业课表查询
     *
     * @param semid 学期id
     * @param zyid  专业id
     * @return 专业课表
     */
    @AutoLog(value = "课表查询-专业课表查询")
    @ApiOperation(value = "课表查询-专业课表查询", notes = "课表查询-专业课表查询")
    @GetMapping("/zykb")
    public Result<JSONObject> zykb(@RequestParam Integer semid, @RequestParam String zyid) {
        // 返回值
        JSONObject result = new JSONObject();

        // 获取班级信息
        List<JSONObject> bjList = commonApi.queryBanJiListBySpecId(CommonApi.COMMON_TOKEN_KEY, zyid).getResult();
        // 最终显示的班级信息
        List<JSONObject> bjs = Lists.newArrayList();
        for (JSONObject bj : bjList) {
            // 排课明细数据
            List<PkmxResult> data = this.getPkmxList(semid, bj.getInteger("id"));
            // 该班级该学期没有排课明细，则跳过
            if (data.size() <= 0) {
                continue;
            }
            this.sort(data);
            this.checkIsHb(data);
            bj.put("kbs", data);
            bjs.add(bj);
        }

        result.put("data", bjs);
        this.setZyDataAndSemData(semid, zyid, result);
        return Result.OK(result);
    }

    /**
     * 全校课表查询
     *
     * @param semid 学期id
     * @param zyid  专业id
     * @return 全校课表
     */
    @AutoLog(value = "课表查询-全校课表查询")
    @ApiOperation(value = "课表查询-全校课表查询", notes = "课表查询-全校课表查询")
    @GetMapping("/qxkb")
    public Result<JSONObject> qxkb(@RequestParam Integer semid, @RequestParam String zyid) {

        // 返回值
        JSONObject result = new JSONObject();

        // 获取班级信息
        List<JSONObject> bjList = commonApi.queryBanJiListBySpecId(CommonApi.COMMON_TOKEN_KEY, zyid).getResult();
        // 最终显示的班级信息
        List<JSONObject> bjs = Lists.newArrayList();
        for (JSONObject bj : bjList) {
            // 排课明细数据
            List<PkmxResult> data = this.getPkmxList(semid, bj.getInteger("id"));
            // 该班级该学期没有排课明细，则跳过
            if (data.size() <= 0) {
                continue;
            }
            this.sort(data);
            this.checkIsHb(data);
            // 获取班主任名字
            JSONObject bzr = commonApi.queryTeacherByUserId(CommonApi.COMMON_TOKEN_KEY, bj.getString("bzrUserId")).getResult();
            bj.put("bzrName", bzr != null ? bzr.getString("xm") : "");
            bj.put("kbs", data);
            bjs.add(bj);
        }

        result.put("data", bjs);
        this.setZyDataAndSemData(semid, zyid, result);
        return Result.OK(result);
    }

    /**
     * 班级、教室、教师课表导出
     *
     * @param semid     学期id
     * @param bjid      班级id
     * @param teacherid 教师id
     * @param jsid      教室id
     * @param response  response
     */
    @GetMapping("/exportExcel")
    public Result<?> exportExcel(Integer semid, Integer bjid, Integer teacherid, Integer jsid, HttpServletResponse response) {

        JSONObject result = null;
        String title = null;
        if (bjid != null) {
            result = this.banJiKeBiao(semid, bjid).getResult();
            title = String.format("%s(%s)", result.getString("bjName"), result.getString("semester"));
        } else if (teacherid != null) {
            result = this.lskb(semid, teacherid).getResult();
            title = String.format("%s(%s)", result.getString("lsName"), result.getString("semester"));
        } else if (jsid != null) {
            result = this.jskb(semid, jsid).getResult();
            title = String.format("%s(%s)", result.getString("jsName"), result.getString("semester"));
        } else {
            return Result.error("导出失败");
        }
        List<PkmxResult> data = result.getJSONArray("data").toJavaList(PkmxResult.class);

        try {
            ServletOutputStream out = response.getOutputStream();
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(title + ".xls", "UTF-8"));
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);

            excelService.export(title, data, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 专业、全校课表
     *
     * @param semid    学期id
     * @param zyid     专业id
     * @param response response
     * @return
     */
    @GetMapping("/exportKbsExcel")
    public Result<?> exportExcel(@RequestParam Integer semid, @RequestParam("specid") String zyid, HttpServletResponse response) {

        JSONObject result = this.zykb(semid, zyid).getResult();
        try {
            ServletOutputStream out = response.getOutputStream();
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("课表.xls", "UTF-8"));
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);

            excelService.exportKbs(result, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }








    /*-----------------------------------------------------------------------------------------------*/

    /**
     * 填充专业和学期信息
     *
     * @param semid  学期id
     * @param zyid   专业id
     * @param result 填充至此对象
     */
    private void setZyDataAndSemData(Integer semid, String zyid, JSONObject result) {
        JSONObject semester = commonApi.querySemesterById(CommonApi.COMMON_TOKEN_KEY, semid).getResult();
        result.put("semester", semester != null ? semester.getString("xqmc") : "");
        JSONObject specialty = commonApi.querySpecialtyById(CommonApi.COMMON_TOKEN_KEY, Integer.parseInt(zyid)).getResult();
        result.put("specialty", specialty != null ? specialty.getString("zymc") : "");
    }

    /**
     * 获取排课明细列表
     *
     * @param semid 学期id
     * @param xzbid 班级id
     * @return 排课明细列表
     */
    private List<PkmxResult> getPkmxList(Integer semid, Integer xzbid) {
        return this.getPkmxList(semid, xzbid, null);
    }

    /**
     * 获取排课明细列表
     *
     * @param semid     学期id
     * @param xzbid     班级id
     * @param paikeList 排课信息列表
     * @return 排课明细列表
     */
    private List<PkmxResult> getPkmxList(Integer semid, Integer xzbid, List<JSONObject> paikeList) {
        // 获取排课信息；列表
        if (paikeList == null) {
            paikeList = scheduleApi.queryPaiKe(PkParam.getBySemidAndJxbid(semid, xzbid)).getResult().getRecords();
        }
        // 排课明细数据
        List<PkmxResult> data = Lists.newArrayList();
        for (JSONObject paike : paikeList) {
            List<PkmxResult> temp = scheduleApi.queryByPkid(paike.getInteger("id")).getResult().getRecords();
            data.addAll(temp);
        }
        return data;
    }

    /**
     * 使用stream进行排序，先按照周几进行升序，其次按照节次进行升序
     *
     * @param kbs 课表
     */
    private void sort(List<PkmxResult> kbs) {
        kbs = kbs.stream().sorted(
                Comparator.comparing(PkmxResult::getWeek).thenComparing(PkmxResult::getSection)
        ).collect(Collectors.toList());
    }

    /**
     * 填充上课地点
     *
     * @param kbs 课表
     */
    private void fillingJsmc(List<PkmxResult> kbs) {
        for (PkmxResult item : kbs) {
            item.setJsmc(jxzyApi.queryNameById(item.getJsid()));
        }
    }

    /**
     * 验证是否合班，并填充上课地点
     *
     * @param kbs 课表
     */
    private void checkIsHb(List<PkmxResult> kbs) {
        List<PkmxResult> data = Lists.newArrayList();
        // 对合班的进行处理
        for (PkmxResult item : kbs) {
            int i = data.indexOf(item);
            if (i >= 0) {
                data.get(i).setIsHb(true);
                continue;
            }
            item.setJsmc(jxzyApi.queryNameById(item.getJsid()));
            data.add(item);
        }
        kbs = data;
    }
}
